<template>
	<view class="component-page">
		<view class="page-header">
			<view class="back-button" @click="backToHome">
				<text class="back-icon">←</text>
				<text>返回</text>
			</view>
			<text class="page-title">网络请求管理</text>
		</view>
		
		<view class="demo-section">
			<view class="section-title">
				请求测试
			</view>
			
			<view class="request-panel">
				<view class="request-form">
					<view class="form-group">
						<text class="form-label">请求地址</text>
						<input 
							class="form-input" 
							v-model="requestUrl" 
							placeholder="输入API地址，如https://api.example.com/data"
						/>
					</view>
					
					<view class="form-group">
						<text class="form-label">请求方法</text>
						<view class="method-selector">
							<view 
								class="method-item" 
								v-for="(method, index) in requestMethods" 
								:key="index"
								:class="{ active: requestMethod === method }"
								@click="requestMethod = method"
							>
								{{ method }}
							</view>
						</view>
					</view>
					
					<view class="form-group" v-if="requestMethod !== 'GET'">
						<text class="form-label">请求数据</text>
						<textarea 
							class="form-textarea" 
							v-model="requestData" 
							placeholder="输入JSON格式的请求数据"
						></textarea>
					</view>
					
					<view class="form-group">
						<text class="form-label">自定义请求头</text>
						<view class="custom-headers">
							<view class="header-item" v-for="(header, index) in requestHeaders" :key="index">
								<view class="header-content">
									<view class="header-name">
										<input 
											class="header-input" 
											v-model="header.name" 
											placeholder="Header Name"
										/>
									</view>
									<view class="header-value">
										<input 
											class="header-input" 
											v-model="header.value" 
											placeholder="Header Value"
										/>
									</view>
								</view>
								<view class="header-remove" @click="removeHeader(index)">×</view>
							</view>
							
							<view class="add-header" @click="addHeader">
								<text class="add-icon">+</text>
								<text>添加请求头</text>
							</view>
						</view>
					</view>
					
					<view class="form-group">
						<text class="form-label">请求选项</text>
						<view class="request-options">
							<view class="option-item">
								<checkbox 
									:checked="withLoading" 
									@change="onLoadingChange"
								/>
								<text class="option-text">显示加载提示</text>
							</view>
							<view class="option-item">
								<checkbox 
									:checked="withRetry" 
									@change="onRetryChange"
								/>
								<text class="option-text">自动重试</text>
								<view class="retry-count" v-if="withRetry">
									<text>重试次数:</text>
									<input 
										class="count-input" 
										type="number" 
										v-model="retryCount" 
										:disabled="!withRetry"
									/>
								</view>
							</view>
							<view class="option-item">
								<checkbox 
									:checked="withTimeout" 
									@change="onTimeoutChange"
								/>
								<text class="option-text">请求超时</text>
								<view class="timeout-value" v-if="withTimeout">
									<text>超时时间(ms):</text>
									<input 
										class="count-input" 
										type="number" 
										v-model="timeoutValue" 
										:disabled="!withTimeout"
									/>
								</view>
							</view>
						</view>
					</view>
				</view>
				
				<view class="action-buttons">
					<button 
						class="send-button" 
						:disabled="!requestUrl || isLoading" 
						@click="sendRequest"
					>
						{{ isLoading ? '发送中...' : '发送请求' }}
					</button>
				</view>
			</view>
		</view>
		
		<view class="demo-section" v-if="responseData">
			<view class="section-title">
				响应结果
				<text class="response-time" v-if="responseTime">
					({{ responseTime }}ms)
				</text>
			</view>
			
			<view class="response-panel">
				<view class="response-status" :class="getStatusClass(responseStatus)">
					<text class="status-code">{{ responseStatus }}</text>
					<text class="status-text">{{ getStatusText(responseStatus) }}</text>
				</view>
				
				<view class="response-tabs">
					<view 
						class="tab-item" 
						v-for="(tab, index) in responseTabs" 
						:key="index"
						:class="{ active: currentTab === index }"
						@click="currentTab = index"
					>
						{{ tab.name }}
					</view>
				</view>
				
				<view class="response-content">
					<!-- 响应数据 -->
					<view class="response-data" v-if="currentTab === 0">
						<scroll-view class="data-scroll" scroll-y>
							<text class="data-text" :style="{ whiteSpace: 'pre-wrap' }">{{ formatJson(responseData) }}</text>
						</scroll-view>
					</view>
					
					<!-- 响应头 -->
					<view class="response-headers" v-else-if="currentTab === 1">
						<scroll-view class="headers-scroll" scroll-y>
							<view 
								class="header-row" 
								v-for="(value, name, index) in responseHeaders" 
								:key="index"
							>
								<text class="header-name">{{ name }}:</text>
								<text class="header-value">{{ value }}</text>
							</view>
						</scroll-view>
					</view>
					
					<!-- 请求日志 -->
					<view class="response-logs" v-else>
						<scroll-view class="logs-scroll" scroll-y>
							<view class="log-item" v-for="(log, index) in requestLogs" :key="index">
								<text class="log-time">{{ log.time }}</text>
								<text class="log-message" :class="log.type">{{ log.message }}</text>
							</view>
						</scroll-view>
						
						<view class="logs-actions">
							<button class="clear-logs-button" @click="clearLogs">清空日志</button>
						</view>
					</view>
				</view>
			</view>
		</view>
		
		<view class="demo-section">
			<view class="section-title">功能特性</view>
			<view class="feature-list">
				<view class="feature-item">
					<view class="feature-icon">🔄</view>
					<view class="feature-info">
						<text class="feature-title">请求拦截器</text>
						<text class="feature-desc">自定义请求前的预处理逻辑</text>
					</view>
				</view>
				<view class="feature-item">
					<view class="feature-icon">📊</view>
					<view class="feature-info">
						<text class="feature-title">响应拦截器</text>
						<text class="feature-desc">统一处理响应数据和错误</text>
					</view>
				</view>
				<view class="feature-item">
					<view class="feature-icon">⚡</view>
					<view class="feature-info">
						<text class="feature-title">自动重试机制</text>
						<text class="feature-desc">网络不稳定时自动重新请求</text>
					</view>
				</view>
				<view class="feature-item">
					<view class="feature-icon">🔒</view>
					<view class="feature-info">
						<text class="feature-title">请求取消功能</text>
						<text class="feature-desc">支持取消正在进行的请求</text>
					</view>
				</view>
				<view class="feature-item">
					<view class="feature-icon">📱</view>
					<view class="feature-info">
						<text class="feature-title">跨平台支持</text>
						<text class="feature-desc">适配各类小程序和App环境</text>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue';
import xlRequest from '@/components/xl-request';

// 请求URL
const requestUrl = ref('https://jsonplaceholder.typicode.com/posts/1');
// 请求方法
const requestMethod = ref('GET');

const requestMethods = ['GET', 'POST', 'PUT', 'DELETE'];
// 请求数据
const requestData = ref('{\n  "title": "测试标题",\n  "body": "测试内容",\n  "userId": 1\n}');
// 请求头
const requestHeaders = ref([
	{ name: 'Content-Type', value: 'application/json' }
]);

// 请求选项
const withLoading = ref(true);
const withRetry = ref(false);
const retryCount = ref(3);
const withTimeout = ref(false);
const timeoutValue = ref(10000);

// 响应相关
const isLoading = ref(false);
const responseData = ref(null);
const responseStatus = ref(null);
const responseHeaders = ref({});
const responseTime = ref(null);
const requestLogs = ref([]);

// 响应选项卡
const responseTabs = ref([
	{ name: '响应数据' },
	{ name: '响应头' },
	{ name: '请求日志' }
]);
const currentTab = ref(0);

// 返回首页
const backToHome = () => {
	uni.navigateBack();
};

// 添加请求头
const addHeader = () => {
	requestHeaders.value.push({ name: '', value: '' });
};

// 移除请求头
const removeHeader = (index) => {
	requestHeaders.value.splice(index, 1);
};

// 加载提示变更
const onLoadingChange = (e) => {
	withLoading.value = e.detail.value;
};

// 自动重试变更
const onRetryChange = (e) => {
	withRetry.value = e.detail.value;
};

// 请求超时变更
const onTimeoutChange = (e) => {
	withTimeout.value = e.detail.value;
};

// 获取状态类名
const getStatusClass = (status) => {
	if (!status) return '';
	
	if (status >= 200 && status < 300) {
		return 'success';
	} else if (status >= 400 && status < 500) {
		return 'client-error';
	} else if (status >= 500) {
		return 'server-error';
	} else {
		return 'info';
	}
};

// 获取状态文本
const getStatusText = (status) => {
	const statusMap = {
		200: 'OK',
		201: 'Created',
		204: 'No Content',
		400: 'Bad Request',
		401: 'Unauthorized',
		403: 'Forbidden',
		404: 'Not Found',
		422: 'Unprocessable Entity',
		500: 'Internal Server Error',
		502: 'Bad Gateway',
		503: 'Service Unavailable',
		504: 'Gateway Timeout'
	};
	
	return statusMap[status] || 'Unknown Status';
};

// 格式化JSON
const formatJson = (data) => {
	if (typeof data === 'string') {
		try {
			return JSON.stringify(JSON.parse(data), null, 2);
		} catch (e) {
			return data;
		}
	}
	
	return JSON.stringify(data, null, 2);
};

// 添加日志
const addLog = (message, type = 'info') => {
	const now = new Date();
	const timeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}.${now.getMilliseconds().toString().padStart(3, '0')}`;
	
	requestLogs.value.push({
		time: timeStr,
		message,
		type
	});
};

// 清空日志
const clearLogs = () => {
	requestLogs.value = [];
};

// 发送请求
const sendRequest = () => {
	// 验证URL
	if (!requestUrl.value) {
		uni.showToast({
			title: '请输入请求地址',
			icon: 'none'
		});
		return;
	}
	
	// 设置状态
	isLoading.value = true;
	currentTab.value = 0;
	
	// 记录请求开始时间
	const startTime = Date.now();
	
	// 添加请求日志
	addLog(`开始请求: ${requestMethod.value} ${requestUrl.value}`, 'info');
	
	// 处理请求头
	const headers = {};
	requestHeaders.value.forEach(header => {
		if (header.name && header.value) {
			headers[header.name] = header.value;
		}
	});
	
	// 处理请求数据
	let data = null;
	if (requestMethod.value !== 'GET' && requestData.value) {
		try {
			data = JSON.parse(requestData.value);
			addLog(`请求数据: ${requestData.value}`, 'info');
		} catch (e) {
			addLog(`请求数据解析错误: ${e.message}`, 'error');
			isLoading.value = false;
			
			uni.showToast({
				title: '请求数据格式不正确',
				icon: 'none'
			});
			return;
		}
	}
	
	// 构建请求选项
	const options = {
		url: requestUrl.value,
		method: requestMethod.value,
		data,
		header: headers,
		showLoading: withLoading.value
	};
	
	// 添加重试选项
	if (withRetry.value) {
		options.retry = {
			count: parseInt(retryCount.value) || 3,
			delay: 1000
		};
		addLog(`启用自动重试: 次数=${retryCount.value}`, 'info');
	}
	
	// 添加超时选项
	if (withTimeout.value) {
		options.timeout = parseInt(timeoutValue.value) || 10000;
		addLog(`设置请求超时: ${timeoutValue.value}ms`, 'info');
	}
	
	// 发送请求
	xlRequest.request(options)
		.then(res => {
			// 计算响应时间
			responseTime.value = Date.now() - startTime;
			
			// 设置响应数据
			responseData.value = res.data;
			responseStatus.value = res.statusCode;
			responseHeaders.value = res.header || {};
			
			// 添加响应日志
			addLog(`请求成功: 状态码 ${res.statusCode}`, 'success');
			addLog(`响应时间: ${responseTime.value}ms`, 'info');
			
			// 恢复状态
			isLoading.value = false;
		})
		.catch(err => {
			// 计算响应时间
			responseTime.value = Date.now() - startTime;
			
			// 设置响应数据
			responseData.value = err.data || { error: err.errMsg || '请求失败' };
			responseStatus.value = err.statusCode || 0;
			responseHeaders.value = err.header || {};
			
			// 添加错误日志
			addLog(`请求失败: ${err.errMsg || JSON.stringify(err)}`, 'error');
			
			// 恢复状态
			isLoading.value = false;
		});
};

// 生命周期处理
onMounted(() => {
	// 初始化请求库
	addLog('请求组件已初始化', 'info');
});
</script>

<style lang="scss">
.component-page {
	padding: 30rpx;
	background-color: #f7f7f7;
	min-height: 100vh;
	box-sizing: border-box;
}

.page-header {
	display: flex;
	align-items: center;
	margin-bottom: 30rpx;
	
	.back-button {
		display: flex;
		align-items: center;
		padding: 10rpx 0;
		margin-right: 20rpx;
		
		.back-icon {
			font-size: 36rpx;
			margin-right: 6rpx;
		}
	}
	
	.page-title {
		font-size: 36rpx;
		font-weight: bold;
		color: #333;
	}
}

.demo-section {
	margin-bottom: 30rpx;
	
	.section-title {
		font-size: 30rpx;
		font-weight: bold;
		margin-bottom: 20rpx;
		display: flex;
		align-items: center;
		
		.response-time {
			font-size: 24rpx;
			font-weight: normal;
			color: #666;
			margin-left: 10rpx;
		}
	}
}

.request-panel, .response-panel {
	background-color: #fff;
	border-radius: 16rpx;
	box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
	overflow: hidden;
	padding: 30rpx;
}

.request-form {
	.form-group {
		margin-bottom: 24rpx;
		
		.form-label {
			font-size: 28rpx;
			font-weight: bold;
			color: #333;
			margin-bottom: 12rpx;
			display: block;
		}
		
		.form-input {
			width: 100%;
			height: 80rpx;
			background-color: #f5f5f5;
			border-radius: 8rpx;
			padding: 0 20rpx;
			font-size: 28rpx;
		}
		
		.form-textarea {
			width: 100%;
			height: 200rpx;
			background-color: #f5f5f5;
			border-radius: 8rpx;
			padding: 20rpx;
			font-size: 28rpx;
			font-family: monospace;
		}
	}
	
	.method-selector {
		display: flex;
		flex-wrap: wrap;
		margin: 0 -10rpx;
		
		.method-item {
			margin: 10rpx;
			padding: 12rpx 24rpx;
			background-color: #f5f5f5;
			border-radius: 30rpx;
			font-size: 26rpx;
			color: #666;
			
			&.active {
				background-color: #007aff;
				color: #fff;
			}
		}
	}
	
	.custom-headers {
		.header-item {
			display: flex;
			align-items: center;
			margin-bottom: 16rpx;
			
			.header-content {
				flex: 1;
				display: flex;
				
				.header-name, .header-value {
					flex: 1;
				}
				
				.header-name {
					margin-right: 16rpx;
				}
				
				.header-input {
					width: 100%;
					height: 70rpx;
					background-color: #f5f5f5;
					border-radius: 8rpx;
					padding: 0 20rpx;
					font-size: 26rpx;
				}
			}
			
			.header-remove {
				width: 60rpx;
				height: 60rpx;
				display: flex;
				align-items: center;
				justify-content: center;
				font-size: 40rpx;
				color: #ff3b30;
				margin-left: 16rpx;
			}
		}
		
		.add-header {
			display: flex;
			align-items: center;
			padding: 16rpx 0;
			color: #007aff;
			font-size: 28rpx;
			
			.add-icon {
				font-size: 32rpx;
				margin-right: 10rpx;
			}
		}
	}
	
	.request-options {
		.option-item {
			display: flex;
			align-items: center;
			margin-bottom: 20rpx;
			
			.option-text {
				font-size: 28rpx;
				margin-left: 10rpx;
				margin-right: 20rpx;
			}
			
			.retry-count, .timeout-value {
				display: flex;
				align-items: center;
				font-size: 26rpx;
				color: #666;
				
				.count-input {
					width: 100rpx;
					height: 60rpx;
					background-color: #f5f5f5;
					border-radius: 8rpx;
					padding: 0 10rpx;
					font-size: 26rpx;
					margin-left: 10rpx;
					text-align: center;
				}
			}
		}
	}
}

.action-buttons {
	margin-top: 20rpx;
	
	.send-button {
		width: 100%;
		height: 88rpx;
		line-height: 88rpx;
		background-color: #007aff;
		color: #fff;
		font-size: 30rpx;
		border-radius: 44rpx;
		
		&:disabled {
			opacity: 0.6;
		}
	}
}

.response-panel {
	.response-status {
		display: flex;
		align-items: center;
		padding: 20rpx;
		border-radius: 8rpx;
		margin-bottom: 20rpx;
		
		&.success {
			background-color: rgba(76, 217, 100, 0.1);
			
			.status-code {
				background-color: #4cd964;
			}
		}
		
		&.info {
			background-color: rgba(0, 122, 255, 0.1);
			
			.status-code {
				background-color: #007aff;
			}
		}
		
		&.client-error {
			background-color: rgba(255, 149, 0, 0.1);
			
			.status-code {
				background-color: #ff9500;
			}
		}
		
		&.server-error {
			background-color: rgba(255, 59, 48, 0.1);
			
			.status-code {
				background-color: #ff3b30;
			}
		}
		
		.status-code {
			font-size: 26rpx;
			font-weight: bold;
			color: #fff;
			padding: 6rpx 16rpx;
			border-radius: 30rpx;
			margin-right: 16rpx;
		}
		
		.status-text {
			font-size: 28rpx;
			color: #333;
		}
	}
	
	.response-tabs {
		display: flex;
		border-bottom: 1px solid #f5f5f5;
		margin-bottom: 20rpx;
		
		.tab-item {
			flex: 1;
			text-align: center;
			padding: 20rpx 0;
			font-size: 28rpx;
			color: #666;
			position: relative;
			
			&.active {
				color: #007aff;
				font-weight: bold;
				
				&:after {
					content: '';
					position: absolute;
					bottom: 0;
					left: 50%;
					transform: translateX(-50%);
					width: 40rpx;
					height: 4rpx;
					background-color: #007aff;
					border-radius: 2rpx;
				}
			}
		}
	}
	
	.response-content {
		height: 400rpx;
		
		.data-scroll, .headers-scroll, .logs-scroll {
			height: 100%;
			
			&.logs-scroll {
				height: calc(100% - 80rpx);
			}
		}
		
		.data-text {
			font-family: monospace;
			font-size: 26rpx;
			line-height: 1.4;
			color: #333;
		}
		
		.header-row {
			display: flex;
			padding: 10rpx 0;
			border-bottom: 1px solid #f5f5f5;
			
			&:last-child {
				border-bottom: none;
			}
			
			.header-name {
				width: 30%;
				font-size: 26rpx;
				font-weight: bold;
				color: #333;
				padding-right: 20rpx;
			}
			
			.header-value {
				flex: 1;
				font-size: 26rpx;
				color: #666;
				word-break: break-all;
			}
		}
		
		.log-item {
			display: flex;
			padding: 10rpx 0;
			
			.log-time {
				font-size: 24rpx;
				color: #999;
				margin-right: 16rpx;
				flex-shrink: 0;
			}
			
			.log-message {
				flex: 1;
				font-size: 26rpx;
				color: #666;
				
				&.info {
					color: #007aff;
				}
				
				&.success {
					color: #4cd964;
				}
				
				&.error {
					color: #ff3b30;
				}
			}
		}
		
		.logs-actions {
			margin-top: 20rpx;
			
			.clear-logs-button {
				width: 100%;
				height: 60rpx;
				line-height: 60rpx;
				font-size: 26rpx;
				color: #666;
				background-color: #f5f5f5;
				border-radius: 30rpx;
			}
		}
	}
}

.feature-list {
	background-color: #fff;
	border-radius: 16rpx;
	box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
	overflow: hidden;
	padding: 10rpx 0;
	
	.feature-item {
		display: flex;
		align-items: center;
		padding: 24rpx 30rpx;
		border-bottom: 1px solid #f5f5f5;
		
		&:last-child {
			border-bottom: none;
		}
		
		.feature-icon {
			width: 80rpx;
			height: 80rpx;
			border-radius: 16rpx;
			background: linear-gradient(45deg, #5AC8FA, #B6DCFE);
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 40rpx;
			margin-right: 24rpx;
		}
		
		.feature-info {
			flex: 1;
			
			.feature-title {
				font-size: 30rpx;
				font-weight: bold;
				color: #333;
				margin-bottom: 6rpx;
				display: block;
			}
			
			.feature-desc {
				font-size: 26rpx;
				color: #666;
				display: block;
			}
		}
	}
}
</style> 